<?php

namespace App\Admin\Forms\Voter;

use App\Jobs\Voter\SimulateVotePlayerJob;
use App\Models\User\WxUser;
use App\Models\Voter\WxVoter;
use App\Models\Voter\WxVoterPlayer;
use App\Models\Voter\WxVoterPlayerBallot;
use App\Wen\Utils\UserUtils;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use Dcat\Admin\Widgets\Form;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

class SimulateVoteForm extends Form implements LazyRenderable
{
    use LazyWidget;

    /**
     * 处理表单请求.
     *
     * @param array $input
     *
     * @return mixed
     */
    public function handle(array $input)
    {
        $voter_id = $input['id'];
        $uid = $input['user_id'];
        $player_id = $input['player_id'];
        $num = $input['num'];
        $later = $input['later'] ?? 0;

        if(_empty_($num)){
            return $this->response()
                ->error('参数错误');
        }
        $voter = WxVoter::find($voter_id);
        if ($voter) {

            // 使用Carbon进行日期时间比较
            $now = Carbon::now();
            $endTime = Carbon::parse($voter->end_time);
            $startTime = Carbon::parse($voter->start_time);

            if ($now->gt($endTime)) {
                // 当前时间已超过end_time
//                return $this->response()
//                    ->error('当前时间已超过投票截止时间');
            } else {
                // 当前时间未超过end_time
            }

            if ($now->gt($startTime)) {
                // 当前时间已超过start_time

            } else {
                // 当前时间未超过start_time
//                return $this->response()
//                    ->error('当前时间未达到投票开始时间');
            }
        } else {
            return $this->response()->error('选票活动不存在');
        }

        if(_empty_($uid) && _empty_($player_id)){
            $user_day_limit = $voter->user_day_limit;
            $user_total_limit = $voter->user_total_limit;
            $total_player_count = WxVoterPlayer::where('status', 1)->where('voter_id', $voter_id)->count();
            $limit_per = 1;
            if($user_total_limit > 0){
                $limit_per = $user_total_limit;
            }else if($user_day_limit > 0){
                $limit_per = $user_day_limit;
            }
            if($total_player_count <= 0){
                return $this->response()
                    ->error('一个选手也没有，无法模拟投票');
            }


            $remaining = $num;
            $average = $remaining / $total_player_count;

            $variance = $limit_per;
            // 初始化分配数组
            $distribution = [];

            // 随机分配数值，同时确保数值在平均数附近波动
            for ($i = 0; $i < $total_player_count; $i++) {
                // 随机生成一个数值，确保它在平均数附近波动
                $value = rand(max(1, floor($average - $variance)), ceil($average + $variance));
                if($value > 0){
                    // 确保总和不超过原始数
                    if (array_sum($distribution) + $value > $remaining) {
                        $value = $remaining - array_sum($distribution);
                    }
                    $distribution[] = $value;
                }else{
                    $distribution[] = 0;
                }
            }

            // 随机打乱分配数组，增加随机性
            shuffle($distribution);

            foreach ($distribution as $i => $part_num){
                $player = WxVoterPlayer::where('voter_id', $voter_id)->where('status', 1)->offset($i)->limit(1)->first();
                if($player){


                    $totalVotes = $part_num;
                    if ($totalVotes <= $limit_per) {
                        $robots = [$totalVotes];
                    }else{
                        // 计算需要的机器人数量
                        $robotsNeeded = ceil($totalVotes / $limit_per);
                        // 初始化机器人和投票分配数组
                        $robots = [];
                        // 随机分配投票给机器人
                        for ($i = 0; $i < $robotsNeeded; $i++) {
                            // 确保每个机器人的投票数在1和最大票数之间
                            $votes = rand(1, min($limit_per, $totalVotes - array_sum($robots)));
                            if($votes > 0){
                                $robots[] = $votes;
                                $totalVotes -= $votes;
                            }else{
//                                $robots[] = 0;
                            }
                        }
                        // 确保总票数正确
                        if (array_sum($robots) != $part_num) {
                            // 调整最后一个机器人的投票数以匹配总票数
                            while ($totalVotes > $limit_per){
                                if($limit_per > 1){
                                    $votes = rand(1, $limit_per);
                                }else{
                                    $votes = 1;
                                }
                                if($votes > 0){
                                    $robots[] = $votes;
                                    $totalVotes -= $votes;
                                }else{
//                                    $robots[] = 0;
                                }
                            }
                            if($totalVotes > 0){
                                if($robots[count($robots) - 1] + $totalVotes > $limit_per){
                                    $robots[count($robots) - 1] = $totalVotes;
                                }else{
                                    $robots[count($robots) - 1] += $totalVotes;
                                }
                            }
                        }
                    }

                    if($robots){
                        $text_[] = "----------------------------------------------------------------\n".'选手编号'.$player->relative_id.'预计共'.$part_num.'票，明细如下：';
                        foreach ($robots as $robot_num){
                            if($robot_num > 0){
                                $robot_uid = UserUtils::get_a_random_robot_uid();
                                if($later == 1){
                                    SimulateVotePlayerJob::dispatch($robot_uid, $voter_id, $player->id, $robot_num)->delay(now()->addMinutes(mini_rand(1, 30)));
                                }else{
                                    $ballot = new WxVoterPlayerBallot();
                                    $ballot->user_id = $robot_uid;
                                    $ballot->voter_id = $voter_id;
                                    $ballot->player_id = $player->id;
                                    $ballot->num = $robot_num;
                                    $r = $ballot->save();
                                }
                                $text_[] = '模拟投票：机器人'.$robot_uid.'->选手编号'.$player->relative_id.'投'.$robot_num.'票';
                            }
                        }
                    }
                }
            }

            _logger_(__file__, __line__, implode("\n", $text_));

            return $this->response()
                ->success('操作成功，投票明细请看日志记录.')
                ->refresh();
        }else{
            if(_empty_($uid) || _empty_($player_id)){
                return $this->response()
                    ->error('参数错误');
            }
            $player = WxVoterPlayer::where('user_id', $player_id)->where('voter_id', $voter_id)->first();
            if(!$player){
                return $this->response()->error('选手不存在');
            }

//        $rest = $this->get_user_voter_rest_ballot($voter, $uid);
//        if($rest < $num){
////            return $this->response()->error('您剩余的票数为'.$rest.'，不足以本次投票');
//        }

            DB::beginTransaction();
            try {
                // todo:
                $ballot = new WxVoterPlayerBallot();
                $ballot->user_id = $uid;
                $ballot->voter_id = $voter->id;
                $ballot->player_id = $player->id;
                $ballot->num = $num;
                $r = $ballot->save();
                if($r){
                    DB::commit();
                    return $this->response()
                        ->success('操作成功.')
                        ->refresh();
                }
                DB::rollBack();
                return $this->response()->error('错误');
            } catch (\Exception $e) {
                DB::rollBack();
                _logger_(__file__, __line__, $e->getMessage());
                return $this->response()->error('错误');
            }
        }
    }

    /**
     * 构建表单.
     */
    public function form()
    {
        $voter_id = $this->payload["id"];

        $this->html(function () {
            return '<div style="background-color: powderblue;color: #414750;padding: 10px;border-radius: 5px;">小技巧：若你不想限定 <b>投票用户</b> 和 <b>选手</b>，则系统调用机器人对所有参加的选手进行随机投票，此时你应该把票数设置的大点</div>';
        }, '');

        $last_arr = [];
        $users_arr = WxVoterPlayer::where('voter_id', $voter_id)->orderBy('relative_id', 'asc')->pluck('user_id');
        if($users_arr){
            $last_arr = WxUser::whereIn('id', $users_arr)->pluck('user_name', 'id')->toArray();
        }

        $this->hidden('id')->value($voter_id);

        $this->select('user_id', '投票用户')->options(function ($id) {
            if($id){
                $user = WxUser::find($id);
                if ($user) {
                    return [$user->id => $user->user_name];
                }
            }
        })->ajax('select/users');

        $this->select('player_id', '选择选手')->options($last_arr);

        $this->number('num', '票数')->default(1);

        $this->switch('later', '延时')->help('系统会计算派出多少机器人合适，若机器人较多，打开延时，则会在30分钟内完成该数量的模拟投票')->default(0);

    }
}
